package sdk

/*
   Copyright 2016 Alexander I.Grafov <grafov@gmail.com>
   Copyright 2016-2019 The Grafana SDK authors

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

   ॐ तारे तुत्तारे तुरे स्व
*/

import (
	
	
	
	
)

// Each panel may be one of these types.
const (
	CustomType panelType = iota
	DashlistType
	GraphType
	TableType
	TextType
	PluginlistType
	AlertlistType
	SinglestatType
	StatType
	RowType
	BarGaugeType
	HeatmapType
	TimeseriesType
	LogsType
	GaugeType
)

const MixedSource = "-- Mixed --"

type RepeatDirection string

const (
	RepeatDirectionVertical   RepeatDirection = "v"
	RepeatDirectionHorizontal RepeatDirection = "h"
)

type (
	// Panel represents panels of different types defined in Grafana.
	Panel struct {
		CommonPanel
		// Should be initialized only one type of panels.
		// OfType field defines which of types below will be used.
		*GraphPanel
		*TablePanel
		*TextPanel
		*SinglestatPanel
		*StatPanel
		*DashlistPanel
		*PluginlistPanel
		*RowPanel
		*AlertlistPanel
		*BarGaugePanel
		*HeatmapPanel
		*TimeseriesPanel
		*LogsPanel
		*GaugePanel
		*CustomPanel
	}
	panelType   int8
	CommonPanel struct {
		Datasource *DatasourceRef `json:"datasource,omitempty"` // metrics
		Editable   bool           `json:"editable"`
		Error      bool           `json:"error"`
		GridPos    struct {
			H *int `json:"h,omitempty"`
			W *int `json:"w,omitempty"`
			X *int `json:"x,omitempty"`
			Y *int `json:"y,omitempty"`
		} `json:"gridPos,omitempty"`
		Height           interface{}      `json:"height,omitempty"` // general
		HideTimeOverride *bool            `json:"hideTimeOverride,omitempty"`
		ID               uint             `json:"id"`
		IsNew            bool             `json:"isNew"`
		Links            []Link           `json:"links,omitempty"`    // general
		MinSpan          *float32         `json:"minSpan,omitempty"`  // templating options
		OfType           panelType        `json:"-"`                  // it required for defining type of the panel
		Renderer         *string          `json:"renderer,omitempty"` // display styles
		Repeat           *string          `json:"repeat,omitempty"`   // templating options
		RepeatDirection  *RepeatDirection `json:"repeatDirection,omitempty"`

		// RepeatIteration *int64   `json:"repeatIteration,omitempty"`
		RepeatPanelID *uint `json:"repeatPanelId,omitempty"`
		ScopedVars    map[string]struct {
			Selected bool   `json:"selected"`
			Text     string `json:"text"`
			Value    string `json:"value"`
		} `json:"scopedVars,omitempty"`
		Span        float32 `json:"span"`                  // general
		Title       string  `json:"title"`                 // general
		Description *string `json:"description,omitempty"` // general
		Transparent bool    `json:"transparent"`
		Type        string  `json:"type"`
	}
	GraphPanel struct {
		AliasColors interface{} `json:"aliasColors"` // XXX
		Bars        bool        `json:"bars"`
		DashLength  *uint       `json:"dashLength,omitempty"`
		Dashes      *bool       `json:"dashes,omitempty"`
		Decimals    *int        `json:"decimals,omitempty"`
		Fill        int         `json:"fill"`
		//		Grid        grid        `json:"grid"` obsoleted in 4.1 by xaxis and yaxis

		Legend          Legend           `json:"legend,omitempty"`
		LeftYAxisLabel  *string          `json:"leftYAxisLabel,omitempty"`
		Lines           bool             `json:"lines"`
		Linewidth       uint             `json:"linewidth"`
		NullPointMode   string           `json:"nullPointMode"`
		Percentage      bool             `json:"percentage"`
		Pointradius     float32          `json:"pointradius"`
		Points          bool             `json:"points"`
		RightYAxisLabel *string          `json:"rightYAxisLabel,omitempty"`
		SeriesOverrides []SeriesOverride `json:"seriesOverrides,omitempty"`
		SpaceLength     *uint            `json:"spaceLength,omitempty"`
		Stack           bool             `json:"stack"`
		SteppedLine     bool             `json:"steppedLine"`
		Targets         []Target         `json:"targets,omitempty"`
		Thresholds      []Threshold      `json:"thresholds,omitempty"`
		TimeFrom        *string          `json:"timeFrom,omitempty"`
		TimeShift       *string          `json:"timeShift,omitempty"`
		Tooltip         Tooltip          `json:"tooltip"`
		XAxis           bool             `json:"x-axis,omitempty"`
		YAxis           bool             `json:"y-axis,omitempty"`
		YFormats        []string         `json:"y_formats,omitempty"`
		Xaxis           Axis             `json:"xaxis"` // was added in Grafana 4.x?
		Yaxes           []Axis           `json:"yaxes"` // was added in Grafana 4.x?
		FieldConfig     *FieldConfig     `json:"fieldConfig,omitempty"`
	}
	FieldConfig struct {
		Defaults  FieldConfigDefaults   `json:"defaults"`
		Overrides []FieldConfigOverride `json:"overrides"`
	}
	Options struct {
		Orientation   string        `json:"orientation"`
		TextMode      string        `json:"textMode"`
		ColorMode     string        `json:"colorMode"`
		GraphMode     string        `json:"graphMode"`
		JustifyMode   string        `json:"justifyMode"`
		DisplayMode   string        `json:"displayMode"`
		Content       string        `json:"content"`
		Mode          string        `json:"mode"`
		ReduceOptions ReduceOptions `json:"reduceOptions"`
		Text          *TextOptions  `json:"text,omitempty"`
	}
	TextOptions struct {
		ValueSize int `json:"valueSize,omitempty"`
		TitleSize int `json:"titleSize,omitempty"`
	}
	ReduceOptions struct {
		Values bool     `json:"values"`
		Fields string   `json:"fields"`
		Calcs  []string `json:"calcs"`
	}
	Threshold struct {
		// the alert threshold value, we do not omitempty, since 0 is a valid
		// threshold
		Value float32 `json:"value"`
		// critical, warning, ok, custom
		ColorMode string `json:"colorMode,omitempty"`
		// gt or lt
		Op   string `json:"op,omitempty"`
		Fill bool   `json:"fill"`
		Line bool   `json:"line"`
		// hexadecimal color (e.g. #629e51, only when ColorMode is "custom")
		FillColor string `json:"fillColor,omitempty"`
		// hexadecimal color (e.g. #629e51, only when ColorMode is "custom")
		LineColor string `json:"lineColor,omitempty"`
		// left or right
		Yaxis string `json:"yaxis,omitempty"`
	}

	Tooltip struct {
		Shared       bool   `json:"shared"`
		ValueType    string `json:"value_type"`
		MsResolution bool   `json:"msResolution,omitempty"` // was added in Grafana 3.x
		Sort         int    `json:"sort,omitempty"`
	}
	TablePanel struct {
		Columns   []Column      `json:"columns"`
		Sort      *Sort         `json:"sort,omitempty"`
		Styles    []ColumnStyle `json:"styles"`
		Transform string        `json:"transform"`
		Targets   []Target      `json:"targets,omitempty"`
		Scroll    bool          `json:"scroll"` // from grafana 3.x
	}
	TextPanel struct {
		Content     string        `json:"content"`
		Mode        string        `json:"mode"`
		PageSize    uint          `json:"pageSize"`
		Scroll      bool          `json:"scroll"`
		ShowHeader  bool          `json:"showHeader"`
		Sort        Sort          `json:"sort"`
		Styles      []ColumnStyle `json:"styles"`
		FieldConfig FieldConfig   `json:"fieldConfig"`
		Options     struct {
			Content string `json:"content"`
			Mode    string `json:"mode"`
		} `json:"options"`
	}
	SinglestatPanel struct {
		Colors          []string    `json:"colors"`
		ColorValue      bool        `json:"colorValue"`
		ColorBackground bool        `json:"colorBackground"`
		Decimals        int         `json:"decimals"`
		Format          string      `json:"format"`
		Gauge           Gauge       `json:"gauge,omitempty"`
		MappingType     *uint       `json:"mappingType,omitempty"`
		MappingTypes    []*MapType  `json:"mappingTypes,omitempty"`
		MaxDataPoints   *IntString  `json:"maxDataPoints,omitempty"`
		NullPointMode   string      `json:"nullPointMode"`
		Postfix         *string     `json:"postfix,omitempty"`
		PostfixFontSize *string     `json:"postfixFontSize,omitempty"`
		Prefix          *string     `json:"prefix,omitempty"`
		PrefixFontSize  *string     `json:"prefixFontSize,omitempty"`
		RangeMaps       []*RangeMap `json:"rangeMaps,omitempty"`
		SparkLine       SparkLine   `json:"sparkline,omitempty"`
		Targets         []Target    `json:"targets,omitempty"`
		Thresholds      string      `json:"thresholds"`
		ValueFontSize   string      `json:"valueFontSize"`
		ValueMaps       []ValueMap  `json:"valueMaps"`
		ValueName       string      `json:"valueName"`
	}
	StatPanel struct {
		Targets     []Target    `json:"targets,omitempty"`
		Options     StatOptions `json:"options"`
		FieldConfig FieldConfig `json:"fieldConfig"`
	}
	StatOptions struct {
		Orientation   string        `json:"orientation"`
		TextMode      string        `json:"textMode"`
		ColorMode     string        `json:"colorMode"`
		GraphMode     string        `json:"graphMode"`
		JustifyMode   string        `json:"justifyMode"`
		ReduceOptions ReduceOptions `json:"reduceOptions"`
		Text          *TextOptions  `json:"text,omitempty"`
	}
	DashlistPanel struct {
		Mode     string   `json:"mode"`
		Query    string   `json:"query"`
		Tags     []string `json:"tags"`
		FolderID int      `json:"folderId"`
		Limit    int      `json:"limit"`
		Headings bool     `json:"headings"`
		Recent   bool     `json:"recent"`
		Search   bool     `json:"search"`
		Starred  bool     `json:"starred"`
	}
	PluginlistPanel struct {
		Limit int `json:"limit,omitempty"`
	}
	AlertlistPanel struct {
		OnlyAlertsOnDashboard bool     `json:"onlyAlertsOnDashboard"`
		Show                  string   `json:"show"`
		SortOrder             int      `json:"sortOrder"`
		Limit                 int      `json:"limit"`
		StateFilter           []string `json:"stateFilter"`
		NameFilter            string   `json:"nameFilter,omitempty"`
		DashboardTags         []string `json:"dashboardTags,omitempty"`
	}
	BarGaugePanel struct {
		Options     Options     `json:"options"`
		Targets     []Target    `json:"targets,omitempty"`
		FieldConfig FieldConfig `json:"fieldConfig"`
	}
	RowPanel struct {
		Panels    []Panel `json:"panels"`
		Collapsed bool    `json:"collapsed"`
	}
	HeatmapPanel struct {
		Cards struct {
			CardPadding *float64 `json:"cardPadding"`
			CardRound   *float64 `json:"cardRound"`
		} `json:"cards"`
		Color struct {
			CardColor   string   `json:"cardColor"`
			ColorScale  string   `json:"colorScale"`
			ColorScheme string   `json:"colorScheme"`
			Exponent    float64  `json:"exponent"`
			Min         *float64 `json:"min,omitempty"`
			Max         *float64 `json:"max,omitempty"`
			Mode        string   `json:"mode"`
		} `json:"color"`
		DataFormat      string `json:"dataFormat"`
		HideZeroBuckets bool   `json:"hideZeroBuckets"`
		HighlightCards  bool   `json:"highlightCards"`
		Legend          struct {
			Show bool `json:"show"`
		} `json:"legend"`
		ReverseYBuckets bool     `json:"reverseYBuckets"`
		Targets         []Target `json:"targets,omitempty"`
		Tooltip         struct {
			Show          bool `json:"show"`
			ShowHistogram bool `json:"showHistogram"`
		} `json:"tooltip"`
		TooltipDecimals int `json:"tooltipDecimals"`
		XAxis           struct {
			Show bool `json:"show"`
		} `json:"xAxis"`
		XBucketNumber *float64 `json:"xBucketNumber"`
		XBucketSize   *string  `json:"xBucketSize"`
		YAxis         struct {
			Decimals    *int     `json:"decimals"`
			Format      string   `json:"format"`
			LogBase     int      `json:"logBase"`
			Show        bool     `json:"show"`
			Max         *string  `json:"max"`
			Min         *string  `json:"min"`
			SplitFactor *float64 `json:"splitFactor"`
		} `json:"yAxis"`
		YBucketBound  string   `json:"yBucketBound"`
		YBucketNumber *float64 `json:"yBucketNumber"`
		YBucketSize   *float64 `json:"yBucketSize"`
	}
	TimeseriesPanel struct {
		Targets     []Target          `json:"targets,omitempty"`
		Options     TimeseriesOptions `json:"options"`
		FieldConfig FieldConfig       `json:"fieldConfig"`
	}
	TimeseriesOptions struct {
		Legend  TimeseriesLegendOptions  `json:"legend,omitempty"`
		Tooltip TimeseriesTooltipOptions `json:"tooltip,omitempty"`
	}
	TimeseriesLegendOptions struct {
		Calcs       []string `json:"calcs"`
		Show        *bool    `json:"showLegend,omitempty"`
		DisplayMode string   `json:"displayMode"`
		Placement   string   `json:"placement"`
	}
	TimeseriesTooltipOptions struct {
		Mode string `json:"mode"`
	}
	FieldConfigDefaults struct {
		Unit       string            `json:"unit"`
		NoValue    string            `json:"noValue,omitempty"`
		Decimals   *int              `json:"decimals,omitempty"`
		Min        *float64          `json:"min,omitempty"`
		Max        *float64          `json:"max,omitempty"`
		Color      FieldConfigColor  `json:"color"`
		Thresholds Thresholds        `json:"thresholds"`
		Custom     FieldConfigCustom `json:"custom"`
		Links      []Link            `json:"links,omitempty"`
	}
	FieldConfigOverrideProperty struct {
		ID    string      `json:"id"`
		Value interface{} `json:"value"`
	}
	FieldConfigOverride struct {
		Matcher struct {
			ID      string `json:"id"`
			Options string `json:"options"`
		} `json:"matcher"`
		Properties []FieldConfigOverrideProperty `json:"properties"`
	}
	FieldConfigCustom struct {
		AxisLabel         string `json:"axisLabel,omitempty"`
		AxisPlacement     string `json:"axisPlacement"`
		AxisSoftMin       *int   `json:"axisSoftMin,omitempty"`
		AxisSoftMax       *int   `json:"axisSoftMax,omitempty"`
		BarAlignment      int    `json:"barAlignment"`
		DrawStyle         string `json:"drawStyle"`
		FillOpacity       int    `json:"fillOpacity"`
		GradientMode      string `json:"gradientMode"`
		LineInterpolation string `json:"lineInterpolation"`
		LineWidth         int    `json:"lineWidth"`
		PointSize         int    `json:"pointSize"`
		ShowPoints        string `json:"showPoints"`
		SpanNulls         bool   `json:"spanNulls"`
		HideFrom          struct {
			Legend  bool `json:"legend"`
			Tooltip bool `json:"tooltip"`
			Viz     bool `json:"viz"`
		} `json:"hideFrom"`
		LineStyle struct {
			Fill string `json:"fill"`
		} `json:"lineStyle"`
		ScaleDistribution struct {
			Type string `json:"type"`
			Log  int    `json:"log,omitempty"`
		} `json:"scaleDistribution"`
		Stacking struct {
			Group string `json:"group"`
			Mode  string `json:"mode"`
		} `json:"stacking"`
		ThresholdsStyle struct {
			Mode string `json:"mode"`
		} `json:"thresholdsStyle"`
	}
	Thresholds struct {
		Mode  string          `json:"mode"`
		Steps []ThresholdStep `json:"steps"`
	}
	ThresholdStep struct {
		Color string   `json:"color"`
		Value *float64 `json:"value"`
	}
	FieldConfigColor struct {
		Mode       string `json:"mode"`
		FixedColor string `json:"fixedColor,omitempty"`
		SeriesBy   string `json:"seriesBy,omitempty"`
	}
	LogsPanel struct {
		Targets []Target    `json:"targets,omitempty"`
		Options LogsOptions `json:"options,omitempty"`
	}
	LogsOptions struct {
		DedupStrategy      string `json:"dedupStrategy"`
		WrapLogMessage     bool   `json:"wrapLogMessage"`
		ShowTime           bool   `json:"showTime"`
		ShowLabels         bool   `json:"showLabels"`
		ShowCommonLabels   bool   `json:"showCommonLabels"`
		PrettifyLogMessage bool   `json:"prettifyLogMessage"`
		SortOrder          string `json:"sortOrder"`
		EnableLogDetails   bool   `json:"enableLogDetails"`
	}
	GaugePanel struct {
		Targets     []Target    `json:"targets,omitempty"`
		Options     StatOptions `json:"options"`
		FieldConfig FieldConfig `json:"fieldConfig"`
	}
	CustomPanel map[string]interface{}
)

// for a graph panel
type (
	Axis struct {
		Format   string       `json:"format"`
		LogBase  int          `json:"logBase"`
		Decimals int          `json:"decimals,omitempty"`
		Max      *FloatString `json:"max,omitempty"`
		Min      *FloatString `json:"min,omitempty"`
		Show     bool         `json:"show"`
		Label    string       `json:"label,omitempty"`
	}
	SeriesOverride struct {
		Alias         string      `json:"alias"`
		Bars          *bool       `json:"bars,omitempty"`
		Color         *string     `json:"color,omitempty"`
		Dashes        *bool       `json:"dashes,omitempty"`
		Fill          *int        `json:"fill,omitempty"`
		FillBelowTo   *string     `json:"fillBelowTo,omitempty"`
		Legend        *bool       `json:"legend,omitempty"`
		Lines         *bool       `json:"lines,omitempty"`
		LineWidth     *int        `json:"linewidth,omitempty"`
		Stack         *BoolString `json:"stack,omitempty"`
		Transform     *string     `json:"transform,omitempty"`
		YAxis         *int        `json:"yaxis,omitempty"`
		ZIndex        *int        `json:"zindex,omitempty"`
		NullPointMode *string     `json:"nullPointMode,omitempty"`
	}
	Sort struct {
		Col  int  `json:"col"`
		Desc bool `json:"desc"`
	}
	Legend struct {
		AlignAsTable bool  `json:"alignAsTable"`
		Avg          bool  `json:"avg"`
		Current      bool  `json:"current"`
		HideEmpty    bool  `json:"hideEmpty"`
		HideZero     bool  `json:"hideZero"`
		Max          bool  `json:"max"`
		Min          bool  `json:"min"`
		RightSide    bool  `json:"rightSide"`
		Show         bool  `json:"show"`
		SideWidth    *uint `json:"sideWidth,omitempty"`
		Total        bool  `json:"total"`
		Values       bool  `json:"values"`
	}
)

// for a table
type (
	Column struct {
		TextType string `json:"text"`
		Value    string `json:"value"`
	}
	ColumnStyle struct {
		Alias           *string    `json:"alias"`
		DateFormat      *string    `json:"dateFormat,omitempty"`
		Pattern         string     `json:"pattern"`
		Type            string     `json:"type"`
		ColorMode       *string    `json:"colorMode,omitempty"`
		Colors          *[]string  `json:"colors,omitempty"`
		Decimals        *int       `json:"decimals,omitempty"`
		Thresholds      *[]string  `json:"thresholds,omitempty"`
		Unit            *string    `json:"unit,omitempty"`
		MappingType     int        `json:"mappingType,omitempty"`
		ValueMaps       []ValueMap `json:"valueMaps,omitempty"`
		Link            bool       `json:"link,omitempty"`
		LinkTooltip     *string    `json:"linkTooltip,omitempty"`
		LinkUrl         *string    `json:"linkUrl,omitempty"`
		LinkTargetBlank bool       `json:"linkTargetBlank,omitempty"`
	}
)

// for a stat
type (
	ValueMap struct {
		Op       string `json:"op"`
		TextType string `json:"text"`
		Value    string `json:"value"`
	}
	Gauge struct {
		MaxValue         float32 `json:"maxValue"`
		MinValue         float32 `json:"minValue"`
		Show             bool    `json:"show"`
		ThresholdLabels  bool    `json:"thresholdLabels"`
		ThresholdMarkers bool    `json:"thresholdMarkers"`
	}
	SparkLine struct {
		FillColor *string  `json:"fillColor,omitempty"`
		Full      bool     `json:"full,omitempty"`
		LineColor *string  `json:"lineColor,omitempty"`
		Show      bool     `json:"show,omitempty"`
		YMin      *float64 `json:"ymin,omitempty"`
		YMax      *float64 `json:"ymax,omitempty"`
	}
)

// for an any panel
type Target struct {
	RefID      string         `json:"refId"`
	Datasource *DatasourceRef `json:"datasource,omitempty"`
	Hide       bool           `json:"hide,omitempty"`

	// For PostgreSQL
	Table        string `json:"table,omitempty"`
	TimeColumn   string `json:"timeColumn,omitempty"`
	MetricColumn string `json:"metricColumn,omitempty"`
	RawSql       string `json:"rawSql,omitempty"`
	Select       [][]struct {
		Params []string `json:"params,omitempty"`
		Type   string   `json:"type,omitempty"`
	} `json:"select,omitempty"`
	Where []struct {
		Type     string   `json:"type,omitempty"`
		Name     string   `json:"name,omitempty"`
		Params   []string `json:"params,omitempty"`
		Datatype string   `json:"datatype,omitempty"`
	} `json:"where,omitempty"`
	Group []struct {
		Type   string   `json:"type,omitempty"`
		Params []string `json:"params,omitempty"`
	} `json:"group,omitempty"`

	// For Prometheus
	Expr           string `json:"expr,omitempty"`
	IntervalFactor int    `json:"intervalFactor,omitempty"`
	Interval       string `json:"interval,omitempty"`
	Step           int    `json:"step,omitempty"`
	LegendFormat   string `json:"legendFormat,omitempty"`
	Instant        bool   `json:"instant,omitempty"`
	Format         string `json:"format,omitempty"`

	// For InfluxDB
	Measurement string `json:"measurement,omitempty"`

	// For Elasticsearch
	DsType  *string `json:"dsType,omitempty"`
	Metrics []struct {
		ID    string `json:"id"`
		Field string `json:"field"`
		Type  string `json:"type"`
	} `json:"metrics,omitempty"`
	Query      string `json:"query,omitempty"`
	Alias      string `json:"alias,omitempty"`
	RawQuery   bool   `json:"rawQuery,omitempty"`
	TimeField  string `json:"timeField,omitempty"`
	BucketAggs []struct {
		ID       string `json:"id"`
		Field    string `json:"field"`
		Type     string `json:"type"`
		Settings struct {
			Interval    string      `json:"interval,omitempty"`
			MinDocCount interface{} `json:"min_doc_count"`
			Order       string      `json:"order,omitempty"`
			OrderBy     string      `json:"orderBy,omitempty"`
			Size        string      `json:"size,omitempty"`
		} `json:"settings"`
	} `json:"bucketAggs,omitempty"`

	// For Graphite
	Target string `json:"target,omitempty"`

	// For CloudWatch
	Namespace  string            `json:"namespace,omitempty"`
	MetricName string            `json:"metricName,omitempty"`
	Statistics []string          `json:"statistics,omitempty"`
	Dimensions map[string]string `json:"dimensions,omitempty"`
	Period     string            `json:"period,omitempty"`
	Region     string            `json:"region,omitempty"`

	// For the Stackdriver data source. Find out more information at
	// https:/grafana.com/docs/grafana/v6.0/features/datasources/stackdriver/
	ProjectName        string                    `json:"projectName,omitempty"`
	AlignOptions       []StackdriverAlignOptions `json:"alignOptions,omitempty"`
	AliasBy            string                    `json:"aliasBy,omitempty"`
	MetricType         string                    `json:"metricType,omitempty"`
	MetricKind         string                    `json:"metricKind,omitempty"`
	Filters            []string                  `json:"filters,omitempty"`
	AlignmentPeriod    string                    `json:"alignmentPeriod,omitempty"`
	CrossSeriesReducer string                    `json:"crossSeriesReducer,omitempty"`
	PerSeriesAligner   string                    `json:"perSeriesAligner,omitempty"`
	ValueType          string                    `json:"valueType,omitempty"`
	Preprocessor       string                    `json:"preprocessor,omitempty"`
	GroupBys           []string                  `json:"groupBys,omitempty"`
	Tags               []struct {
		Key      string `json:"key,omitempty"`
		Operator string `json:"operator,omitempty"`
		Value    string `json:"value,omitempty"`
	} `json:"tags,omitempty"`
}

// StackdriverAlignOptions defines the list of alignment options shown in
// Grafana during query configuration.
type StackdriverAlignOptions struct {
	Expanded bool                     `json:"expanded"`
	Label    string                   `json:"label"`
	Options  []StackdriverAlignOption `json:"options"`
}

// StackdriverAlignOption defines a single alignment option shown in Grafana
// during query configuration.
type StackdriverAlignOption struct {
	Label       string   `json:"label"`
	MetricKinds []string `json:"metricKinds"`
	Text        string   `json:"text"`
	Value       string   `json:"value"`
	ValueTypes  []string `json:"valueTypes"`
}

type MapType struct {
	Name  *string `json:"name,omitempty"`
	Value *int    `json:"value,omitempty"`
}

type RangeMap struct {
	From *string `json:"from,omitempty"`
	Text *string `json:"text,omitempty"`
	To   *string `json:"to,omitempty"`
}

// NewDashlist initializes panel with a dashlist panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   DashlistType,
			Title:    ,
			Type:     "dashlist",
			Renderer: &,
			IsNew:    true},
		DashlistPanel: &DashlistPanel{}}
}

// NewGraph initializes panel with a graph panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   GraphType,
			Title:    ,
			Type:     "graph",
			Renderer: &,
			Span:     12,
			IsNew:    true},
		GraphPanel: &GraphPanel{
			NullPointMode: "connected",
			Pointradius:   5,
			XAxis:         true,
			YAxis:         true,
		}}
}

// NewTimeseries initializes panel with a timeseries panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}

	return &Panel{
		CommonPanel: CommonPanel{
			OfType: TimeseriesType,
			Title:  ,
			Type:   "timeseries",
			Span:   12,
			IsNew:  true,
		},
		TimeseriesPanel: &TimeseriesPanel{
			FieldConfig: FieldConfig{
				Defaults: FieldConfigDefaults{
					Color: FieldConfigColor{
						Mode:       "palette-classic",
						FixedColor: "green",
						SeriesBy:   "last",
					},
				},
			},
		},
	}
}

// NewLogs initializes a new panel as a Logs panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}

	return &Panel{
		CommonPanel: CommonPanel{
			OfType: LogsType,
			Title:  ,
			Type:   "logs",
			Span:   12,
			IsNew:  true,
		},
		LogsPanel: &LogsPanel{},
	}
}

// NewGauge initializes a new panel as a Gauge panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}

	return &Panel{
		CommonPanel: CommonPanel{
			OfType: GaugeType,
			Title:  ,
			Type:   "gauge",
			Span:   12,
			IsNew:  true,
		},
		GaugePanel: &GaugePanel{
			Options: StatOptions{
				GraphMode: "none",
				ReduceOptions: ReduceOptions{
					Calcs: []string{"lastNotNull"},
				},
				Text: &TextOptions{},
			},
			FieldConfig: FieldConfig{
				Defaults: FieldConfigDefaults{
					Color: FieldConfigColor{
						Mode:       "thresholds",
						FixedColor: "green",
						SeriesBy:   "last",
					},
				},
			},
		},
	}
}

// NewTable initializes panel with a table panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   TableType,
			Title:    ,
			Type:     "table",
			Renderer: &,
			IsNew:    true},
		TablePanel: &TablePanel{}}
}

// NewText initializes panel with a text panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   TextType,
			Title:    ,
			Type:     "text",
			Renderer: &,
			IsNew:    true},
		TextPanel: &TextPanel{}}
}

// NewSinglestat initializes panel with a singlestat panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   SinglestatType,
			Title:    ,
			Type:     "singlestat",
			Renderer: &,
			IsNew:    true},
		SinglestatPanel: &SinglestatPanel{}}
}

// NewStat initializes panel with a stat panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   StatType,
			Title:    ,
			Type:     "stat",
			Renderer: &,
			IsNew:    true,
		},
		StatPanel: &StatPanel{
			Options: StatOptions{
				GraphMode: "none",
				ReduceOptions: ReduceOptions{
					Calcs: []string{"lastNotNull"},
				},
				Text: &TextOptions{},
			},
			FieldConfig: FieldConfig{
				Defaults: FieldConfigDefaults{
					Color: FieldConfigColor{
						Mode:       "thresholds",
						FixedColor: "green",
						SeriesBy:   "last",
					},
				},
			},
		},
	}
}

// NewPluginlist initializes panel with a stat panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   PluginlistType,
			Title:    ,
			Type:     "pluginlist",
			Renderer: &,
			IsNew:    true},
		PluginlistPanel: &PluginlistPanel{}}
}

func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   AlertlistType,
			Title:    ,
			Type:     "alertlist",
			Renderer: &,
			IsNew:    true},
		AlertlistPanel: &AlertlistPanel{}}
}

func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   HeatmapType,
			Title:    ,
			Type:     "heatmap",
			Renderer: &,
			IsNew:    true},
		HeatmapPanel: &HeatmapPanel{}}
}

// NewCustom initializes panel with a stat panel.
func ( string) *Panel {
	if  == "" {
		 = "Panel Title"
	}
	 := "flot"
	return &Panel{
		CommonPanel: CommonPanel{
			OfType:   CustomType,
			Title:    ,
			Type:     "singlestat",
			Renderer: &,
			IsNew:    true},
		CustomPanel: &CustomPanel{}}
}

// ResetTargets delete all targets defined for a panel.
func ( *Panel) () {
	switch .OfType {
	case GraphType:
		.GraphPanel.Targets = nil
	case SinglestatType:
		.SinglestatPanel.Targets = nil
	case StatType:
		.StatPanel.Targets = nil
	case TableType:
		.TablePanel.Targets = nil
	case BarGaugeType:
		.BarGaugePanel.Targets = nil
	case HeatmapType:
		.HeatmapPanel.Targets = nil
	case TimeseriesType:
		.TimeseriesPanel.Targets = nil
	case LogsType:
		.LogsPanel.Targets = nil
	case GaugeType:
		.GaugePanel.Targets = nil
	}
}

// AddTarget adds a new target as defined in the argument
// but with refId letter incremented. Value of refID from
// the argument will be used only if no target with such
// value already exists.
func ( *Panel) ( *Target) {
	switch .OfType {
	case GraphType:
		.GraphPanel.Targets = append(.GraphPanel.Targets, *)
	case SinglestatType:
		.SinglestatPanel.Targets = append(.SinglestatPanel.Targets, *)
	case StatType:
		.StatPanel.Targets = append(.StatPanel.Targets, *)
	case TableType:
		.TablePanel.Targets = append(.TablePanel.Targets, *)
	case HeatmapType:
		.HeatmapPanel.Targets = append(.HeatmapPanel.Targets, *)
	case TimeseriesType:
		.TimeseriesPanel.Targets = append(.TimeseriesPanel.Targets, *)
	case LogsType:
		.LogsPanel.Targets = append(.LogsPanel.Targets, *)
	case GaugeType:
		.GaugePanel.Targets = append(.GaugePanel.Targets, *)
	}
	// TODO check for existing refID
}

// SetTarget updates a target if target with such refId exists
// or creates a new one.
func ( *Panel) ( *Target) {
	 := func( *Target,  *[]Target) {
		for ,  := range * {
			if .RefID == .RefID {
				(*)[] = *
				return
			}
		}
		(*) = append((*), *)
	}
	switch .OfType {
	case GraphType:
		(, &.GraphPanel.Targets)
	case SinglestatType:
		(, &.SinglestatPanel.Targets)
	case StatType:
		(, &.StatPanel.Targets)
	case TableType:
		(, &.TablePanel.Targets)
	case HeatmapType:
		(, &.HeatmapPanel.Targets)
	case TimeseriesType:
		(, &.TimeseriesPanel.Targets)
	case LogsType:
		(, &.LogsPanel.Targets)
	case GaugeType:
		(, &.GaugePanel.Targets)
	}
}

// MapDatasources on all existing targets for the panel.
func ( *Panel) ( ...string) {
	 := func( []string,  *[]Target) {
		var  = "A"
		 := *
		 := make([]Target, 0, len()*len())
		* = 
		for ,  := range  {
			for ,  := range  {
				 := 
				.RefID = 
				.Datasource = &DatasourceRef{LegacyName: }
				 = incRefID()
				* = append(*, )
			}
		}
	}
	switch .OfType {
	case GraphType:
		(, &.GraphPanel.Targets)
	case SinglestatType:
		(, &.SinglestatPanel.Targets)
	case StatType:
		(, &.StatPanel.Targets)
	case TableType:
		(, &.TablePanel.Targets)
	case HeatmapType:
		(, &.HeatmapPanel.Targets)
	case TimeseriesType:
		(, &.TimeseriesPanel.Targets)
	case LogsType:
		(, &.LogsPanel.Targets)
	case GaugeType:
		(, &.GaugePanel.Targets)
	}
}

// RepeatTargetsForDatasources repeats all existing targets for a panel
// for all provided in the argument datasources. Existing datasources of
// targets are ignored.
func ( *Panel) ( ...string) {
	 := func( []string,  *[]Target) {
		var  string
		 := len(*)
		for ,  := range  {
			if  <  {
				(*)[].Datasource = &DatasourceRef{LegacyName: }
				 = (*)[].RefID
			} else {
				 := (*)[%]
				 = incRefID()
				.RefID = 
				.Datasource = &DatasourceRef{LegacyName: }
				* = append(*, )
			}
		}
	}
	switch .OfType {
	case GraphType:
		(, &.GraphPanel.Targets)
	case SinglestatType:
		(, &.SinglestatPanel.Targets)
	case StatType:
		(, &.StatPanel.Targets)
	case TableType:
		(, &.TablePanel.Targets)
	case HeatmapType:
		(, &.HeatmapPanel.Targets)
	case TimeseriesType:
		(, &.TimeseriesPanel.Targets)
	case LogsType:
		(, &.LogsPanel.Targets)
	case GaugeType:
		(, &.GaugePanel.Targets)
	}
}

// GetTargets iterates over all panel targets. It just returns nil if
// no targets defined for panel of concrete type.
func ( *Panel) () *[]Target {
	switch .OfType {
	case GraphType:
		return &.GraphPanel.Targets
	case SinglestatType:
		return &.SinglestatPanel.Targets
	case StatType:
		return &.StatPanel.Targets
	case TableType:
		return &.TablePanel.Targets
	case BarGaugeType:
		return &.BarGaugePanel.Targets
	case HeatmapType:
		return &.HeatmapPanel.Targets
	case TimeseriesType:
		return &.TimeseriesPanel.Targets
	case LogsType:
		return &.LogsPanel.Targets
	case GaugeType:
		return &.GaugePanel.Targets
	default:
		return nil
	}
}

type probePanel struct {
	CommonPanel
	//	json.RawMessage
}

func ( *Panel) ( []byte) error {
	var  probePanel
	var  error

	if  = json.Unmarshal(, &);  != nil {
		return 
	}

	.CommonPanel = .CommonPanel
	switch .Type {
	case "graph":
		var  GraphPanel
		.OfType = GraphType
		if  = json.Unmarshal(, &);  == nil {
			.GraphPanel = &
		}
	case "table":
		var  TablePanel
		.OfType = TableType
		if  = json.Unmarshal(, &);  == nil {
			.TablePanel = &
		}
	case "text":
		var  TextPanel
		.OfType = TextType
		if  = json.Unmarshal(, &);  == nil {
			.TextPanel = &
		}
	case "singlestat":
		var  SinglestatPanel
		.OfType = SinglestatType
		if  = json.Unmarshal(, &);  == nil {
			.SinglestatPanel = &
		}
	case "stat":
		var  StatPanel
		.OfType = StatType
		if  = json.Unmarshal(, &);  == nil {
			.StatPanel = &
		}
	case "dashlist":
		var  DashlistPanel
		.OfType = DashlistType
		if  = json.Unmarshal(, &);  == nil {
			.DashlistPanel = &
		}
	case "bargauge":
		var  BarGaugePanel
		.OfType = BarGaugeType
		if  = json.Unmarshal(, &);  == nil {
			.BarGaugePanel = &
		}
	case "heatmap":
		var  HeatmapPanel
		.OfType = HeatmapType
		if  = json.Unmarshal(, &);  == nil {
			.HeatmapPanel = &
		}
	case "timeseries":
		var  TimeseriesPanel
		.OfType = TimeseriesType
		if  = json.Unmarshal(, &);  == nil {
			.TimeseriesPanel = &
		}
	case "logs":
		var  LogsPanel
		.OfType = LogsType
		if  = json.Unmarshal(, &);  == nil {
			.LogsPanel = &
		}
	case "gauge":
		var  GaugePanel
		.OfType = GaugeType
		if  = json.Unmarshal(, &);  == nil {
			.GaugePanel = &
		}
	case "row":
		var  RowPanel
		.OfType = RowType
		if  = json.Unmarshal(, &);  == nil {
			.RowPanel = &
		}
	default:
		var  = make(CustomPanel)
		.OfType = CustomType
		if  = json.Unmarshal(, &);  == nil {
			.CustomPanel = &
		}
	}

	if  != nil && (.Title != "" || .Type != "") {
		 = fmt.Errorf("%w (panel %q of type %q)", , .Title, .Type)
	}

	return 
}

func ( *Panel) () ([]byte, error) {
	switch .OfType {
	case GraphType:
		var  = struct {
			CommonPanel
			GraphPanel
		}{.CommonPanel, *.GraphPanel}
		return json.Marshal()
	case TableType:
		var  = struct {
			CommonPanel
			TablePanel
		}{.CommonPanel, *.TablePanel}
		return json.Marshal()
	case TextType:
		var  = struct {
			CommonPanel
			TextPanel
		}{.CommonPanel, *.TextPanel}
		return json.Marshal()
	case SinglestatType:
		var  = struct {
			CommonPanel
			SinglestatPanel
		}{.CommonPanel, *.SinglestatPanel}
		return json.Marshal()
	case StatType:
		var  = struct {
			CommonPanel
			StatPanel
		}{.CommonPanel, *.StatPanel}
		return json.Marshal()
	case DashlistType:
		var  = struct {
			CommonPanel
			DashlistPanel
		}{.CommonPanel, *.DashlistPanel}
		return json.Marshal()
	case BarGaugeType:
		var  = struct {
			CommonPanel
			BarGaugePanel
		}{.CommonPanel, *.BarGaugePanel}
		return json.Marshal()
	case PluginlistType:
		var  = struct {
			CommonPanel
			PluginlistPanel
		}{.CommonPanel, *.PluginlistPanel}
		return json.Marshal()
	case AlertlistType:
		var  = struct {
			CommonPanel
			AlertlistPanel
		}{.CommonPanel, *.AlertlistPanel}
		return json.Marshal()
	case RowType:
		var  = struct {
			CommonPanel
			RowPanel
		}{.CommonPanel, *.RowPanel}
		return json.Marshal()
	case HeatmapType:
		var  = struct {
			CommonPanel
			HeatmapPanel
		}{.CommonPanel, *.HeatmapPanel}
		return json.Marshal()
	case TimeseriesType:
		var  = struct {
			CommonPanel
			TimeseriesPanel
		}{.CommonPanel, *.TimeseriesPanel}
		return json.Marshal()
	case LogsType:
		var  = struct {
			CommonPanel
			LogsPanel
		}{.CommonPanel, *.LogsPanel}
		return json.Marshal()
	case GaugeType:
		var  = struct {
			CommonPanel
			GaugePanel
		}{.CommonPanel, *.GaugePanel}
		return json.Marshal()
	case CustomType:
		var  = customPanelOutput{
			.CommonPanel,
			*.CustomPanel,
		}
		return json.Marshal()
	}
	return nil, errors.New("can't marshal unknown panel type")
}

type customPanelOutput struct {
	CommonPanel
	CustomPanel
}

func ( customPanelOutput) () ([]byte, error) {
	,  := json.Marshal(.CommonPanel)
	if  != nil {
		return , 
	}
	// Append custom keys to marshalled CommonPanel.
	 := bytes.NewBuffer([:len()-1])

	for ,  := range .CustomPanel {
		.WriteString(`,"`)
		.WriteString()
		.WriteString(`":`)
		,  := json.Marshal()
		if  != nil {
			return , 
		}
		.Write()
	}
	.WriteString("}")
	return .Bytes(), nil
}

func incRefID( string) string {
	 := [0]
	 := int()
	++
	return string(rune())
}